send a GtkWidget** instead of a GtkNotebookPage* when doing tabs DnD, this
authorCarlos Garnacho <carlosg@gnome.org>
Wed, 22 Mar 2006 16:11:48 +0000 (16:11 +0000)
committerCarlos Garnacho <carlosg@src.gnome.org>
Wed, 22 Mar 2006 16:11:48 +0000 (16:11 +0000)
2006-03-22  Carlos Garnacho  <carlosg@gnome.org>

        * gtk/gtknotebook.c: send a GtkWidget** instead of a GtkNotebookPage*
        when doing tabs DnD, this allows DnD interaction with other widgets,
        added some docs for this too.
        * tests/testnotebookdnd.c: add some code to test it.

ChangeLog
ChangeLog.pre-2-10
gtk/gtknotebook.c
tests/testnotebookdnd.c

index 984b10911af2c3610528d4fe34ed5787ec25d603..4d96cb40d23d7dd00be4dc9f17ae0dfd423e1be5 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2006-03-22  Carlos Garnacho  <carlosg@gnome.org>
+
+       * gtk/gtknotebook.c: send a GtkWidget** instead of a GtkNotebookPage*
+       when doing tabs DnD, this allows DnD interaction with other widgets,
+       added some docs for this too.
+       * tests/testnotebookdnd.c: add some code to test it.
+
 2006-03-22  Matthias Clasen  <mclasen@redhat.com>
 
        * gtk/gtk.symbols: 
index 984b10911af2c3610528d4fe34ed5787ec25d603..4d96cb40d23d7dd00be4dc9f17ae0dfd423e1be5 100644 (file)
@@ -1,3 +1,10 @@
+2006-03-22  Carlos Garnacho  <carlosg@gnome.org>
+
+       * gtk/gtknotebook.c: send a GtkWidget** instead of a GtkNotebookPage*
+       when doing tabs DnD, this allows DnD interaction with other widgets,
+       added some docs for this too.
+       * tests/testnotebookdnd.c: add some code to test it.
+
 2006-03-22  Matthias Clasen  <mclasen@redhat.com>
 
        * gtk/gtk.symbols: 
index 9dd499b3d58210ac81d575d751ac4900c60b6806..016d8eb6ecec66784a5ab2df147e77e67a60a338 100644 (file)
@@ -40,7 +40,6 @@
 #include "gtkalias.h"
 #include "gtkdnd.h"
 
-
 #define ARROW_SIZE            12
 #define ARROW_SPACING         0
 #define SCROLL_DELAY_FACTOR   5
@@ -2847,33 +2846,36 @@ gtk_notebook_drag_drop (GtkWidget        *widget,
 static void
 do_detach_tab (GtkNotebook     *from,
               GtkNotebook     *to,
-              GtkNotebookPage *page_info,
+              GtkWidget       *child,
               gint             x,
               gint             y)
 {
-  GtkWidget *child, *tab_label, *menu_label;
+  GtkWidget *tab_label, *menu_label;
   gboolean tab_expand, tab_fill, reorderable, detachable;
   GList *element;
   guint tab_pack;
   gint page_num;
 
-  menu_label = tab_label = child = NULL;
+  menu_label = gtk_notebook_get_menu_label (from, child);
 
-  if (page_info->menu_label)
-    menu_label = g_object_ref (page_info->menu_label);
+  if (menu_label)
+    g_object_ref (menu_label);
 
-  if (page_info->tab_label)
-    tab_label = g_object_ref (page_info->tab_label);
+  tab_label = gtk_notebook_get_tab_label (from, child);
+  
+  if (tab_label)
+    g_object_ref (tab_label);
 
-  if (page_info->child)
-    child = g_object_ref (page_info->child);
+  g_object_ref (child);
 
-  /* preserve properties */
-  tab_expand = page_info->expand;
-  tab_fill = page_info->fill;
-  tab_pack = page_info->pack;
-  reorderable = page_info->reorderable;
-  detachable = page_info->detachable;
+  gtk_container_child_get (GTK_CONTAINER (from),
+                          child,
+                          "tab-expand", &tab_expand,
+                          "tab-fill", &tab_fill,
+                          "tab-pack", &tab_pack,
+                          "reorderable", &reorderable,
+                          "detachable", &detachable,
+                          NULL);
 
   gtk_container_remove (GTK_CONTAINER (from), child);
 
@@ -2912,7 +2914,6 @@ gtk_notebook_drag_data_get (GtkWidget        *widget,
                            guint             time)
 {
   GtkNotebook *dest_notebook, *notebook;
-  gint page_num;
 
   if (data->target != gdk_atom_intern_static_string ("GTK_NOTEBOOK_TAB") &&
       (data->target != gdk_atom_intern_static_string ("application/x-rootwindow-drop") ||
@@ -2920,15 +2921,14 @@ gtk_notebook_drag_data_get (GtkWidget        *widget,
     return;
 
   notebook = GTK_NOTEBOOK (widget);
-  page_num = g_list_index (notebook->children, notebook->cur_page);
 
   if (data->target == gdk_atom_intern_static_string ("GTK_NOTEBOOK_TAB"))
     {
       gtk_selection_data_set (data,
                              data->target,
                              8,
-                             (void*) notebook->cur_page,
-                             sizeof (GtkNotebookPage));
+                             (void*) &notebook->cur_page->child,
+                             sizeof (gpointer));
     }
   else
     {
@@ -2944,7 +2944,7 @@ gtk_notebook_drag_data_get (GtkWidget        *widget,
                                                window_creation_hook_data);
 
       if (dest_notebook)
-       do_detach_tab (notebook, dest_notebook, notebook->cur_page, 0, 0);
+       do_detach_tab (notebook, dest_notebook, notebook->cur_page->child, 0, 0);
     }
 }
 
@@ -2959,7 +2959,7 @@ gtk_notebook_drag_data_received (GtkWidget        *widget,
 {
   GtkNotebook *notebook;
   GtkWidget *source_widget;
-  GtkNotebookPage *page_info;
+  GtkWidget **child;
 
   notebook = GTK_NOTEBOOK (widget);
   source_widget = gtk_drag_get_source_widget (context);
@@ -2967,13 +2967,13 @@ gtk_notebook_drag_data_received (GtkWidget        *widget,
   if (source_widget &&
       data->target == gdk_atom_intern_static_string ("GTK_NOTEBOOK_TAB"))
     {
-      page_info = (void*) data->data;
+      child = (void*) data->data;
 
-      do_detach_tab (GTK_NOTEBOOK (source_widget), notebook, page_info, x, y);
+      do_detach_tab (GTK_NOTEBOOK (source_widget), notebook, *child, x, y);
       gtk_drag_finish (context, TRUE, FALSE, time);
     }
-
-  gtk_drag_finish (context, FALSE, FALSE, time);
+  else
+    gtk_drag_finish (context, FALSE, FALSE, time);
 }
 
 /* Private GtkContainer Methods :
@@ -6920,10 +6920,43 @@ gtk_notebook_get_tab_detachable (GtkNotebook *notebook,
  * @child: a child #GtkWidget
  * @detachable: whether the tab is detachable or not
  *
- * Sets whether the tab can be detached from @notebook to another notebook.
+ * Sets whether the tab can be detached from @notebook to another
+ * notebook or widget.
  *
  * Note that 2 notebooks must share a common group identificator
- * (see gtk_notebook_set_group_id ()) to allow tabs interchange between them.
+ * (see gtk_notebook_set_group_id ()) to allow automatic tabs
+ * interchange between them.
+ *
+ * If you want a widget to interact with a notebook through DnD
+ * (i.e.: accept dragged tabs from it) it must be set as a drop
+ * destination and accept the target "GTK_NOTEBOOK_TAB". The notebook
+ * will fill the selection with a GtkWidget** pointing to the child
+ * widget that corresponds to the dropped tab.
+ *
+ * <informalexample><programlisting>
+ *  static void
+ *  on_drop_zone_drag_data_received (GtkWidget        *widget,
+ *                                   GdkDragContext   *context,
+ *                                   gint              x,
+ *                                   gint              y,
+ *                                   GtkSelectionData *selection_data,
+ *                                   guint             info,
+ *                                   guint             time,
+ *                                   gpointer          user_data)
+ *  {
+ *    GtkWidget *notebook;
+ *    GtkWidget **child;
+ *
+ *    notebook = gtk_drag_get_source_widget (context);
+ *    child = (void*) selection_data->data;
+ *
+ *    process_widget (*child);
+ *    gtk_container_remove (GTK_CONTAINER (notebook), *child);
+ *  }
+ * </programlisting></informalexample>
+ *
+ * If you want a notebook to accept drags from other widgets,
+ * you will have to set your own DnD code to do it.
  *
  * Since: 2.10
  **/
index 4c48af5649e7d84cf38600c5a0494311426515b0..f47d93a6f2bfd0d1199b18053e0bc42851f85150 100644 (file)
@@ -1,3 +1,4 @@
+/* -*- Mode: C; c-file-style: "gnu"; tab-width: 8 -*- */
 /* 
  * GTK - The GIMP Toolkit
  * Copyright (C) 2006  Carlos Garnacho Parro <carlosg@gnome.org>
@@ -64,6 +65,10 @@ gchar *tabs4 [] = {
   NULL
 };
 
+static const GtkTargetEntry button_targets[] = {
+  { "GTK_NOTEBOOK_TAB", GTK_TARGET_SAME_APP, 0 },
+};
+
 static GtkNotebook*
 window_creation_function (GtkNotebook *source_notebook,
                          GtkWidget   *child,
@@ -94,6 +99,46 @@ on_page_reordered (GtkNotebook *notebook, GtkWidget *child, guint page_num, gpoi
   g_print ("page %d reordered\n", page_num);
 }
 
+static void
+on_notebook_drag_begin (GtkWidget      *widget,
+                       GdkDragContext *context,
+                       gpointer        data)
+{
+  GdkPixbuf *pixbuf;
+  guint page_num;
+
+  page_num = gtk_notebook_get_current_page (GTK_NOTEBOOK (widget));
+
+  pixbuf = gtk_widget_render_icon (widget,
+                                  (page_num % 2) ? GTK_STOCK_HELP : GTK_STOCK_STOP,
+                                  GTK_ICON_SIZE_DND, NULL);
+
+  gtk_drag_set_icon_pixbuf (context, pixbuf, 0, 0);
+  g_object_unref (pixbuf);
+}
+
+static void
+on_button_drag_data_received (GtkWidget        *widget,
+                             GdkDragContext   *context,
+                             gint              x,
+                             gint              y,
+                             GtkSelectionData *data,
+                             guint             info,
+                             guint             time,
+                             gpointer          user_data)
+{
+  GtkWidget *source, *tab_label;
+  GtkWidget **child;
+
+  source = gtk_drag_get_source_widget (context);
+  child = (void*) data->data;
+
+  tab_label = gtk_notebook_get_tab_label (GTK_NOTEBOOK (source), *child);
+  g_print ("Removing tab: %s\n", gtk_label_get_text (GTK_LABEL (tab_label)));
+
+  gtk_container_remove (GTK_CONTAINER (source), *child);
+}
+
 static GtkWidget*
 create_notebook (gchar           **labels,
                 gint              group_id,
@@ -131,10 +176,29 @@ create_notebook (gchar           **labels,
 
   g_signal_connect (GTK_NOTEBOOK (notebook), "page-reordered",
                    G_CALLBACK (on_page_reordered), NULL);
-
+  g_signal_connect_after (G_OBJECT (notebook), "drag-begin",
+                         G_CALLBACK (on_notebook_drag_begin), NULL);
   return notebook;
 }
 
+static GtkWidget*
+create_trash_button (void)
+{
+  GtkWidget *button;
+
+  button = gtk_button_new_from_stock (GTK_STOCK_DELETE);
+
+  gtk_drag_dest_set (button,
+                    GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
+                    button_targets,
+                    G_N_ELEMENTS (button_targets),
+                    GDK_ACTION_MOVE);
+
+  g_signal_connect_after (G_OBJECT (button), "drag-data-received",
+                         G_CALLBACK (on_button_drag_data_received), NULL);
+  return button;
+}
+
 gint
 main (gint argc, gchar *argv[])
 {
@@ -143,7 +207,7 @@ main (gint argc, gchar *argv[])
   gtk_init (&argc, &argv);
 
   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-  table = gtk_table_new (2, 2, TRUE);
+  table = gtk_table_new (3, 2, FALSE);
 
   gtk_notebook_set_window_creation_hook (window_creation_function, NULL);
 
@@ -163,6 +227,10 @@ main (gint argc, gchar *argv[])
                             create_notebook (tabs4, GROUP_A, PACK_ALTERNATE, GTK_POS_RIGHT),
                             1, 2, 1, 2);
 
+  gtk_table_attach (GTK_TABLE (table),
+                   create_trash_button (), 1, 2, 2, 3,
+                   GTK_EXPAND | GTK_FILL, GTK_SHRINK, 0, 0);
+
   gtk_container_add (GTK_CONTAINER (window), table);
   gtk_window_set_default_size (GTK_WINDOW (window), 400, 400);
   gtk_widget_show_all (window);